package com.jdrx.ocp.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Maps;
import com.jdrx.ocp.beans.commons.SysConstant;
import com.jdrx.ocp.beans.dto.setting.QuerySettingDTO;
import com.jdrx.ocp.beans.dto.setting.UpdateSettingBatchDTO;
import com.jdrx.ocp.beans.entity.SettingPO;
import com.jdrx.ocp.beans.entity.util.ExceptionMessageFilter;
import com.jdrx.ocp.beans.vo.GroupSettingVO;
import com.jdrx.ocp.beans.vo.SettingVO;
import com.jdrx.ocp.dao.SettingDAO;
import com.jdrx.platform.commons.rest.exception.BizException;
import com.jdrx.platform.jdbc.beans.vo.PageVO;
import com.jdrx.sw.sewage.service.common.RedisService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: Huangxg
 * @Date: 2018/12/7 11:41
 */
@Service
public class SettingService {

    private static Logger logger = LoggerFactory.getLogger(SettingService.class);
    @Autowired
    private SettingDAO settingDAO;

    @Autowired
    private RedisService redisService;


    /**
     * 根据键获取数据
     * @param key
     * @return
     * @throws BizException
     */
    public SettingPO getByKey(String key) throws BizException {
        try{
            SettingPO po =  settingDAO.getByKey(key);
            po.setKey(po.getKey());
            return po;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw new BizException("获取数据失败！");
        }
    }

    /**
     * 删除键
     * @param key
     * @return
     * @throws BizException
     */
    public int deleteByKey(String key,String tid) throws BizException {
        try{
            int i = settingDAO.deleteByKey(key);
            keyMap(tid);
            return i;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw new BizException("删除数据失败！");
        }
    }

    /**
     * 根据条件查询配置
     * @param querMap
     * @return
     * @throws BizException
     */
    public List<SettingPO> listBy(Map<String,Object> querMap) throws BizException {
        try{
            List<SettingPO> list = settingDAO.listBy(querMap);
            for (SettingPO po : list){
                po.setKey(po.getKey());
            }
            return list;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw new BizException("获取数据失败！");
        }
    }

    /**
     * 将配置转成 key-value Map
     * @return
     * @throws BizException
     */
    public Map<String,Object> keyMap(String tid) throws BizException {
        //直接从缓存中获取
        String settingKey = getSettingKey(tid) ;
        logger.info(String.format("settingKey:%s",settingKey));
        Map<String,Object> map = redisService.getMap(settingKey);
        if(map != null){
            return map;
        }else{
            map = new HashMap<>();
        }
        //从数据库中获取
        updateKeyMap(map,tid);
        return map;
    }

    /**
     * 更新缓存
     * @param map
     * @throws BizException
     */
    public void updateKeyMap(Map<String,Object> map , String tid) throws BizException {
        String settingKey = getSettingKey(tid);
        List<SettingPO> list = listBy(Maps.newHashMap());
        for (SettingPO settingPO : list){
            map.put(settingPO.getKey(),settingPO.getValue());
        }
        // 加入缓存
        redisService.setMap(settingKey, map, 0L);
    }

    private String getSettingKey(String tid) {
        tid = formatTid(tid);
        return "";
    }


    private String formatTid(String tid) {
        if (StringUtils.isEmpty(tid)) {
            tid = "";
        } else {
            if(tid.indexOf(",") > 0){
                String[] tids = tid.split(",");
                for (String id : tids){
                    if(StringUtils.isNotEmpty(id)){
                        tid = id;
                        break;
                    }
                }
            }
            tid = tid + ":";
        }
        return tid;
    }

    /**
     * 获取指定key 的值
     * @param key
     * @return
     * @throws BizException
     */
    public Object getSettingByKey(String key,String tid) throws BizException {
        Map<String,Object> map = keyMap(tid);
        if(map != null && map.containsKey(key)){
            return map.get(key);
        }
        return null;
    }

    /**
     * 查询带分页
     * @param querySettingDTO
     * @return
     * @throws BizException
     */
    public PageVO<SettingVO> listByPage(QuerySettingDTO querySettingDTO) throws BizException {
        try{
            Map<String,Object> query = new HashMap<>(3);
            query.put("likeName",querySettingDTO.getName());
            query.put("likeKey",querySettingDTO.getKey());
            Page<SettingPO> page = PageHelper.startPage(querySettingDTO.getPageNum(), querySettingDTO.getPageSize());
            settingDAO.listBy(query);
            PageVO<SettingVO> pageVO = new PageVO<SettingVO>(page);
            List<SettingPO> list = page.getResult();
            List<SettingVO> reList = new ArrayList<>();
            list.forEach(row->{
                SettingVO vo = new SettingVO();
                BeanUtils.copyProperties(row,vo);
                vo.setKey(row.getKey());
                reList.add(vo);
            });
            pageVO.setData(reList);
            return pageVO;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw new BizException("获取数据失败！");
        }
    }

    /**
     * 查询所有配置
     * @return
     * @throws BizException
     */
    public List<SettingVO> queryAll() throws BizException {
        try{
            List<SettingPO> list = listBy(new HashMap<>(1));
            List<SettingVO> reList = new ArrayList<>();
            list.forEach(row -> {
                SettingVO settingVO = new SettingVO();
                BeanUtils.copyProperties(row,settingVO);
                settingVO.setKey(row.getKey());
                reList.add(settingVO);
            });
            return reList;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw new BizException("获取数据失败！");
        }
    }

    /**
     * 对配置列表进行分组
     */
    public List<GroupSettingVO> queryAllForGroup() throws BizException {
        try {
            List<SettingPO> list = listBy(new HashMap<>(1));
            List<GroupSettingVO> reList = new ArrayList<>();
            Map<String,List<SettingVO>> map = new HashMap<>(16);
            //分组
            if (list != null && list.size() > 0) {
                list.forEach(row -> {
                    SettingVO settingVO = new SettingVO();
                    BeanUtils.copyProperties(row, settingVO);
                    if (map.containsKey(row.getGroupName())) {
                        map.get(row.getGroupName()).add(settingVO);
                    } else {
                        List<SettingVO> thisList = new ArrayList<>();
                        thisList.add(settingVO);
                        map.put(row.getGroupName(), thisList);
                    }
                });
                //封装成标准的key - value
                map.entrySet().forEach(item->{
                    GroupSettingVO groupSettingVO = new GroupSettingVO();
                    groupSettingVO.setGroupName(item.getKey());
                    groupSettingVO.setList(item.getValue());
                    reList.add(groupSettingVO);
                });
            }
            return reList;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BizException("获取数据失败！");
        }
    }

    /**
     * 添加配置数据
     * @param settingPO
     * @return
     * @throws BizException
     */
    @Transactional(rollbackFor = Exception.class)
    public int addSetting(SettingPO settingPO , String tid) throws BizException {
        try{
            boolean isHave = keyExist(settingPO.getKey());
            if(isHave){
                throw new BizException("当前键已存在");
            }
            if(settingDAO.insert(settingPO) > 0){
                updateKeyMap(Maps.newHashMap() , tid);
                return 1;
            }
            return 0;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw  new BizException(ExceptionMessageFilter.filter(e.getMessage()));
        }
    }

    /**
     * 更新配置信息
     * @param settingPO
     * @return
     * @throws BizException
     */
    public int updateSetting(SettingPO settingPO , String tid) throws BizException {
        try{
            if(settingDAO.update(settingPO) > 0){
                updateKeyMap(Maps.newHashMap() , tid);
                return 1;
            }
            return 0;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw  new BizException("更新数据失败！");
        }
    }

    /**
     * 检测是否已存在键
     * @param key
     * @return
     * @throws BizException
     */
    public boolean keyExist(String key) throws BizException {
        try {
            Map<String,Object> map = new HashMap<>(3);
            map.put("key",key);
            List<SettingPO> list = settingDAO.listBy(map);
            if(list != null && list.size() > 0){
                return true;
            }
            return false;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw new BizException("检测数据失败！");
        }
    }

    /**
     * 批量更新配置数据
     * @param updateSettingBatchDTO
     * @return
     */
    public boolean updateSettingBatch(UpdateSettingBatchDTO updateSettingBatchDTO , String tid) throws BizException {
        try{
            if(settingDAO.updateBatch(updateSettingBatchDTO.getItems()) > 0){
                updateKeyMap(Maps.newHashMap() , tid);
                return true;
            }
            return false;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw new BizException("更新数据失败！");
        }
    }

}
